package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"time"
)

const (
	gpioBase = "/sys/class/gpio"
)

func callNotify(gpio string) error {
	if gpio != "call_notify" {
		if err := ioutil.WriteFile(filepath.Join(gpioBase, gpio, "value"), []byte(fmt.Sprintf("%d", 1)), 0644); err != nil {
			return fmt.Errorf("门禁呼叫error: %w", err)
		}
		time.Sleep(time.Millisecond * 120)
		if err := ioutil.WriteFile(filepath.Join(gpioBase, gpio, "value"), []byte(fmt.Sprintf("%d", 0)), 0644); err != nil {
			return fmt.Errorf("门禁呼叫error: %w", err)
		}
	} else {
		if err := ioutil.WriteFile(filepath.Join(gpioBase, gpio, "value"), []byte(fmt.Sprintf("%d", 0)), 0644); err != nil {
			return fmt.Errorf("门禁呼叫error: %w", err)
		}
		time.Sleep(time.Millisecond * 120)
		if err := ioutil.WriteFile(filepath.Join(gpioBase, gpio, "value"), []byte(fmt.Sprintf("%d", 1)), 0644); err != nil {
			return fmt.Errorf("门禁呼叫error: %w", err)
		}
	}
	return nil
}

// 初始化GPIO（导出+方向设置）
func initGPIO(gpio string, isOut bool) error {
	// 检查是否已导出
	gpioStr := fmt.Sprintf("gpio%s", gpio)
	gpioPath := filepath.Join(gpioBase, gpioStr)
	if _, err := os.Stat(gpioPath); os.IsNotExist(err) {
		// 导出GPIO
		if err := ioutil.WriteFile(filepath.Join(gpioBase, "export"), []byte(gpio), 0644); err != nil {
			return fmt.Errorf("导出失败: %w", err)
		}
		time.Sleep(100 * time.Millisecond) // 等待系统创建目录
	}

	// 设置方向为输入
	directionFile := filepath.Join(gpioPath, "direction")
	if isOut {
		if err := ioutil.WriteFile(directionFile, []byte("out"), 0644); err != nil {
			return fmt.Errorf("设置方向失败: %w", err)
		}
	} else {
		if err := ioutil.WriteFile(directionFile, []byte("in"), 0644); err != nil {
			return fmt.Errorf("设置方向失败: %w", err)
		}
	}
	logger.Println("GPIO初始化成功")
	return nil
}

// 监听GPIO状态变化
func watchGPIO(gpioNum int, fn func(value int)) error {
	valueFile := filepath.Join(gpioBase, fmt.Sprintf("gpio%d", gpioNum), "value")
	f, err := os.Open(valueFile)
	if err != nil {
		return err
	}
	defer f.Close()
	// 存储上次状态
	lastValue := 1
	for {
		// 读取最新值（ASCII '0'/'1' -> 数值0/1）
		currentValue := readValue(f)
		// 仅当状态变化时触发业务逻辑
		if currentValue != lastValue {
			if currentValue == 0 {
				logger.Printf("状态变化: %d -> %d\n", lastValue, currentValue)
				fn(currentValue)
			}
			lastValue = currentValue
		}
		time.Sleep(time.Millisecond * 100)
	}
}

// 读取当前GPIO值
func readValue(f *os.File) int {
	buf := make([]byte, 1)
	_, _ = f.ReadAt(buf, 0) // 读取当前位置的值
	if buf[0] == '0' {
		return 0
	}
	return 1
}

// 清理资源
func cleanupGPIO(gpioNum int) {
	unexportFile := filepath.Join(gpioBase, "unexport")
	if err := ioutil.WriteFile(unexportFile, []byte(fmt.Sprintf("%d", gpioNum)), 0644); err == nil {
		logger.Println("已清理GPIO资源")
	}
}
